package com.example.monitoring.utils;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.ThreadMXBean;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Arrays;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

/**
 * JMX连接测试工具类
 * 
 * @author rsz
 * @since 2024-04-13
 */
public class JmxConnectionTester {

    public static void main(String[] args) {
        System.out.println("=========== JMX连接测试工具 ===========");
        System.out.println("此工具用于测试JMX连接问题，帮助您排查JMX连接失败的原因");
        System.out.println();
        
        // 提示目标JVM启动参数
        System.out.println("请确保目标JVM已使用以下参数启动:");
        System.out.println("-Dcom.sun.management.jmxremote");
        System.out.println("-Dcom.sun.management.jmxremote.port=9999");
        System.out.println("-Dcom.sun.management.jmxremote.authenticate=false");
        System.out.println("-Dcom.sun.management.jmxremote.ssl=false");
        System.out.println("-Djava.rmi.server.hostname=localhost");
        System.out.println();

        // 确定要测试的主机和端口
        String host = "localhost";
        int[] portsToTest = {1099, 9999, 7199, 8686};
        
        if (args.length >= 1) {
            host = args[0];
            System.out.println("使用指定主机: " + host);
        }
        
        if (args.length >= 2) {
            try {
                portsToTest = new int[] { Integer.parseInt(args[1]) };
                System.out.println("使用指定端口: " + portsToTest[0]);
            } catch (NumberFormatException e) {
                System.out.println("端口格式错误，使用默认端口列表");
            }
        }
        
        System.out.println();
        System.out.println("1. 测试本地JVM连接");
        testLocalJvm();
        
        System.out.println();
        System.out.println("2. 测试端口连通性");
        for (int port : portsToTest) {
            boolean isOpen = isPortOpen(host, port);
            System.out.println("  端口 " + host + ":" + port + " " + (isOpen ? "可连接" : "不可连接"));
        }
        
        System.out.println();
        System.out.println("3. 尝试JMX连接");
        for (int port : portsToTest) {
            if (isPortOpen(host, port)) {
                System.out.println("  尝试连接: " + host + ":" + port);
                testJmxConnection(host, port);
            }
        }
        
        System.out.println();
        System.out.println("4. 常见问题排查");
        System.out.println("  • 确保目标JVM已启动并添加了正确的JMX参数");
        System.out.println("  • 检查防火墙是否允许JMX端口通信");
        System.out.println("  • 确保java.rmi.server.hostname设置为正确的IP地址");
        System.out.println("  • 尝试在目标JVM所在服务器上运行jconsole查看是否可连接");
        System.out.println("  • 查看目标JVM的启动日志是否有JMX相关错误");
    }
    
    /**
     * 测试本地JVM连接
     */
    private static void testLocalJvm() {
        try {
            MBeanServerConnection connection = ManagementFactory.getPlatformMBeanServer();
            System.out.println("  本地JVM MBean服务器连接成功");
            
            // 获取内存信息
            MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
            System.out.println("  堆内存使用: " + memoryBean.getHeapMemoryUsage());
            
            // 获取线程信息
            ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
            System.out.println("  线程数: " + threadBean.getThreadCount());
        } catch (Exception e) {
            System.out.println("  本地JVM连接失败: " + e.getMessage());
        }
    }
    
    /**
     * 测试JMX远程连接
     */
    private static void testJmxConnection(String host, int port) {
        // 尝试不同的JMX URL格式
        String[] jmxUrls = {
            "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi",
            "service:jmx:rmi://" + host + ":" + port + "/jndi/rmi://" + host + ":" + port + "/jmxrmi"
        };
        
        for (String jmxUrl : jmxUrls) {
            try {
                System.out.println("  尝试URL: " + jmxUrl);
                JMXServiceURL serviceUrl = new JMXServiceURL(jmxUrl);
                JMXConnector connector = JMXConnectorFactory.connect(serviceUrl);
                MBeanServerConnection connection = connector.getMBeanServerConnection();
                
                // 获取JVM内存信息
                MemoryMXBean memoryBean = ManagementFactory.newPlatformMXBeanProxy(
                        connection,
                        ManagementFactory.MEMORY_MXBEAN_NAME,
                        MemoryMXBean.class
                );
                System.out.println("  连接成功! 堆内存使用: " + memoryBean.getHeapMemoryUsage());
                
                // 获取线程信息
                ThreadMXBean threadBean = ManagementFactory.newPlatformMXBeanProxy(
                        connection,
                        ManagementFactory.THREAD_MXBEAN_NAME,
                        ThreadMXBean.class
                );
                System.out.println("  线程数: " + threadBean.getThreadCount());
                
                connector.close();
                return;
            } catch (Exception e) {
                System.out.println("  连接失败: " + e.getMessage());
                if (e.getCause() != null) {
                    System.out.println("  原因: " + e.getCause().getMessage());
                }
            }
        }
    }
    
    /**
     * 检查端口是否开放
     */
    private static boolean isPortOpen(String host, int port) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(host, port), 3000);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
} 